package labox.innovation.gameserver.network.clientpackets;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;
import labox.innovation.gameserver.LoginServerThread;
import labox.innovation.gameserver.datatables.CharNameTable;
import labox.innovation.gameserver.datatables.PlayerTemplateTable;
import labox.innovation.gameserver.idfactory.IdFactory;
import labox.innovation.gameserver.instancemanager.QuestManager;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.L2ItemInstance;
import labox.innovation.gameserver.model.L2ShortCut;
import labox.innovation.gameserver.model.Scene;
import labox.innovation.gameserver.model.actor.appearance.PcAppearance;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.quest.Quest;
import labox.innovation.gameserver.model.quest.QuestState;
import labox.innovation.gameserver.network.L2GameClient;
import labox.innovation.gameserver.network.serverpackets.CharCreateFail;
import labox.innovation.gameserver.network.serverpackets.CharSelectionInfo;
import labox.innovation.gameserver.templates.chars.PlayerTemplate;
import labox.innovation.gameserver.templates.chars.PlayerTemplate.TemplateItem;
import labox.innovation.gameserver.templates.chars.PlayerTemplate.TemplateShortCut;
import labox.innovation.util.Util;

/**
 * 客户端提交的创建角色协议
 * 
 * @author Administrator
 * 
 */
public final class CharacterCreate extends L2GameClientPacket {

	private static final String _C__0B_CHARACTERCREATE = "[C] 0B CharacterCreate";

	private static final Logger _log = LoggerFactory.getLogger(CharacterCreate.class.getName());

	//检查注册的角色名称是否符合标准的正则表达式
	private static final Pattern PATTERN = Pattern.compile(Config.CNAME_TEMPLATE);

	private String _name;

	private byte _sex;

	private int _classId;

	@Override
	protected void readImpl() {
		_name = readString();
		_sex = readByte();
		_classId = readByte();
	}

	@Override
	protected void runImpl() {
		//角色名长度不能小于1大于6
		if (_name == null || (_name.length() < 1) || (_name.length() > 6)) {
			if (_log.isDebugEnabled())
				_log.debug("Character Creation Failure: Character name " + _name + " is invalid. Message generated: Your title cannot exceed 6 characters in length. Please try again.");

			sendPacket(new CharCreateFail(CharCreateFail.REASON_16_ENG_CHARS));
			return;
		}

		//检测角色名是否有效
		if (!Util.isAlphaNumeric(_name) || !isValidName(_name) || isFiltedName(_name)) {
			if (_log.isDebugEnabled())
				_log.debug("Character Creation Failure: Character name " + _name + " is invalid. Message generated: Incorrect name. Please try again.");

			sendPacket(new CharCreateFail(CharCreateFail.REASON_INCORRECT_NAME));
			return;
		}

		FuzePcInstance newChar = null;
		PlayerTemplate template = null;

		synchronized (getClient().getAccountName().intern()) {//防止同一个账户的并发创建角色
			//检查此账户创建的角色数量是否已经超过配置的数量
			if (CharNameTable.getInstance().accountCharNumber(getClient().getAccountName()) >= Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT && Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT != 0) {
				if (_log.isDebugEnabled())
					_log.debug("Max number of characters reached. Creation failed.");

				sendPacket(new CharCreateFail(CharCreateFail.REASON_TOO_MANY_CHARACTERS));
				return;
			}

			synchronized (CharNameTable.getInstance()) {//防止不同的账户创建相同的角色名称
				if (CharNameTable.getInstance().doesCharNameExist(_name)) {
					if (_log.isDebugEnabled())
						_log.debug("Character Creation Failure: Message generated: You cannot create another character. Please delete the existing character and try again.");

					sendPacket(new CharCreateFail(CharCreateFail.REASON_NAME_ALREADY_EXISTS));
					return;
				}

				template = PlayerTemplateTable.getInstance().getTemplate(_classId + _sex);

				if (template == null) {
					if (_log.isDebugEnabled())
						_log.debug("Character Creation Failure: " + _name + " classId: " + _classId + " Template: " + template + " Message generated: Your character creation has failed.");

					sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
					return;
				}

				long objectId = IdFactory.getInstance().getNextId(IdFactory.ID_PLAYER);
				newChar = FuzePcInstance.create(objectId, template, getClient().getAccountName(), _name, _sex);
				_log.info("新建角色:", objectId, _name);
				_log.info("账户创建角色:object id" + objectId + " nickname:" + _name, Config.SERVER_ID, getClient().getAccountName());
				//把角色的ID->名称的映射关系保存一下
				CharNameTable.getInstance().addName(newChar);
			}

		}

		initNewChar(getClient(), newChar);

		if (_log.isDebugEnabled()) {
			_log.debug("{} Created new character {}", getClient(), newChar);
		}
		LoginServerThread.getInstance().sendCharacterCounts(getClient().getAccountName());

	}

	/**
	 * 检查是否是符合规范的字符串
	 * @param text
	 * @return
	 */
	private boolean isValidName(String text) {
		Matcher regexp = PATTERN.matcher(text);
		if (!regexp.matches()) {
			return false;
		}
		return true;
	}

	/**
	 * 检查是否是被过滤的字符串
	 * @param text
	 * @return
	 */
	private boolean isFiltedName(String text) {
		for (int i = -1; ++i < Config.NICKNAMEFILTER.length;) {
			if (text.indexOf(Config.NICKNAMEFILTER[i]) >= 0) {
				return true;
			}
		}
		return false;
	}

	private void initNewChar(L2GameClient client, FuzePcInstance newChar) {
		if (_log.isDebugEnabled())
			_log.debug("Character init start");

		PlayerTemplate template = newChar.getTemplate();

		PcAppearance appearance = newChar.getAppearance();

		//付给外形预配置的动画ID
		appearance.setAnimationID(template.get_animationId());

		//付给外形预配置的映射部位ID
		for (Map.Entry<Integer, Integer> paperdoll : template.getPaperDollMapping()) {
			appearance.setPaperdoll(paperdoll.getKey(), paperdoll.getValue());
		}

		//初始化银文
		newChar.addMoneySilver("Init", Config.STARTING_ADENA, null, false);
		//初始化头衔
		newChar.setTitle("");

		//设置自动升级
		newChar.getStat().setAutoAddLevel(true);

		Scene s = FuzeWorld.getInstance().getScene(template._sceneId);
		int x = template._spawnX;
		int y = template._spawnY;
		if (s == null) {
			_log.error("预配置的无效的场景ID:" + template._sceneId, Config.SERVER_ID, null);
			s = FuzeWorld.getInstance().getScene(0);
			x = 404;
			y = 297;
		}
		newChar.getPosition().setScene(s);
		newChar.getPosition().setScenePosition(x, y);

		newChar.setPracticeId(newChar.getTemplate()._pracId);//写入仙魔位ID

		//设置等级
		if (Config.STARTING_LEVEL > 1) {
			newChar.getStat().addLevel(Config.STARTING_LEVEL - 1, false);
		}

		//初始化配置的快捷方式
		for (TemplateShortCut sc : template.getShortCut()) {
			newChar.registerShortCut(new L2ShortCut(sc.getSlot(), sc.getType(), sc.getId()));
		}

		//初始化配置的道具装备
		for (TemplateItem ia : template.getItem()) {

			L2ItemInstance item = newChar.getInventory().addItem("Init", ia.getItemId(), ia.getAmount(), newChar, null);

			if (item == null) {
				_log.error("预配置的无效的道具ID:" + ia.getItemId(), Config.SERVER_ID, null);
				continue;
			}

			if (item.isEquipable() && ia.isEquipped()) {
				newChar.getInventory().equipItem(item);
			}
		}

		newChar.setCurrentHp(newChar.getMaxHp());
		newChar.setCurrentMp(newChar.getMaxMp());

		//根据职业初始化技能
		//		for (L2SkillLearn skill : SkillTreeTable.getInstance().getAvailableSkills(newChar, newChar.getClassId())) {
		//			newChar.addSkill(SkillTable.getInstance().getInfo(skill.getId(), skill.getLevel()), true);
		//			if (Config.DEBUG)
		//				_log.fine("Adding starter skill:" + skill.getId() + " / " + skill.getLevel());
		//		}

		//加入开始的教学任务
		startTutorialQuest(newChar);

		//把角色信息回写数据库
		L2GameClient.saveCharToDisk(newChar);

		CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId());
		client.getConnection().sendPacket(cl);

		client.setCharSelection(cl.getCharInfo());

		if (_log.isDebugEnabled())
			_log.debug("Character init end");
	}

	public void startTutorialQuest(FuzePcInstance player) {
		QuestState qs = player.getQuestState("255_Tutorial");
		Quest q = null;
		if (qs == null)
			q = QuestManager.getInstance().getQuest("255_Tutorial");
		if (q != null)
			q.newQuestState(player);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see labox.innovation.gameserver.clientpackets.ClientBasePacket#getType()
	 */
	@Override
	public String getType() {
		return _C__0B_CHARACTERCREATE;
	}
}
